[infra] Backend integration tests — testcontainers 取代 docker-compose postgres#293
Conversation
Create independent backend-build job that builds image once, then backend and backend-integration jobs download the artifact and run tests in parallel. This reduces total CI time from (build + unit + integration) to (build + max(unit, integration)). Changes: - New backend-build job: build → docker save → upload artifact - backend job: download artifact → docker load → run unit tests - backend-integration job: download artifact → docker load → run integration tests - Both test jobs now depend on backend-build (parallel execution) - notify-discord updated to include backend-build in needs refs #285 Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Ensure docker save command failure fails fast, preventing upload of corrupted artifacts. Add explicit file size validation. refs #285
Ensure backend image build failures are reported as CI failures, not skipped jobs, so PR merge is properly blocked by required checks. The backend-ci gate depends on backend-build, backend, and backend-integration. If backend-build fails, the gate fails, guaranteeing required checks will block merge. Update pr-scope-policy.md to reflect the new gate check name. refs #285
Only fail when backend-build, backend, or backend-integration actually fail. Allow them to be skipped due to scope-gate rules. refs #285
Use allowlist mode: only success or skipped are acceptable. Prevents branch protection bypass when jobs are manually cancelled. refs #285
Cannot dynamically expand needs.$job.result via expressions. Use env variables to pass values, then iterate in shell. Fixes: #288 (comment) refs #285
Replace docker-compose postgres dependency with testcontainers-go. Tests now self-manage PostgreSQL lifecycle via TestMain, removing the need for external DB setup in CI. refs #292 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ontainers) refs #292 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 39 minutes and 39 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
整體概況此變更將後端整合測試的執行方式從 Docker Compose 改為主機端 Go 測試,並利用 testcontainers 動態啟動 PostgreSQL 容器,移除對預構建後端映像的依賴。 變更一覽
關鍵風險評估
|
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | PR 標題清楚說明主要改動:使用 testcontainers 取代 docker-compose 中的 PostgreSQL 管理,這正是本次 PR 的核心目的。 |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
infra/testcontainers-integration-tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
PR Scope Police
Snapshot
|
Integration tests now run natively via testcontainers (setup-go), not inside the app Docker container. The two require_in checks for docker compose run integration build/test no longer apply. refs #293 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/internal/services/testutil_pg_test.go (1)
71-100:⚠️ Potential issue | 🟠 Majorcleanup 位置錯誤會導致 schema 洩漏,且缺少連線池關閉。
newPGTestDB在第 96 行註冊 cleanup,但在此之前有多個失敗路徑(第 76、81、89、93 行的 Fatalf)會跳過 cleanup 執行。若testDB.Open()或migratePGTestDB()失敗,建立的 schema 將永久存留;同時adminDB的連線也會洩漏。此外,即使成功路徑,cleanup 也未關閉adminDB與testDB的連線池,在 shared PostgreSQL container 下會不斷累積 idle connections。修正方式:將 cleanup 移到 schema 建立之後立即註冊,並在 cleanup 中呼叫
testDB.DB().Close()與adminDB.DB().Close()。修正方向
adminDB, err := gorm.Open(postgres.Open(pgContainerURL), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), TranslateError: true, }) if err != nil { t.Fatalf("open postgres admin db: %v", err) } schemaName := "test_" + strings.ReplaceAll(uuid.NewString(), "-", "") if err := adminDB.Exec(fmt.Sprintf(`CREATE SCHEMA IF NOT EXISTS "%s"`, schemaName)).Error; err != nil { t.Fatalf("create schema %s: %v", schemaName, err) } + var testDB *gorm.DB + t.Cleanup(func() { + if testDB != nil { + if sqlDB, err := testDB.DB(); err == nil { + _ = sqlDB.Close() + } + } + if err := adminDB.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS "%s" CASCADE`, schemaName)).Error; err != nil { + t.Errorf("drop schema %s: %v", schemaName, err) + } + if sqlDB, err := adminDB.DB(); err == nil { + _ = sqlDB.Close() + } + }) + - testDB, err := gorm.Open(postgres.Open(withSearchPath(pgContainerURL, schemaName)), &gorm.Config{ + testDB, err = gorm.Open(postgres.Open(withSearchPath(pgContainerURL, schemaName)), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), TranslateError: true, }) if err != nil { t.Fatalf("open postgres test db: %v", err) } if err := migratePGTestDB(testDB); err != nil { t.Fatalf("migrate postgres test db: %v", err) } - t.Cleanup(func() { - if err := adminDB.Exec(fmt.Sprintf(`DROP SCHEMA IF EXISTS "%s" CASCADE`, schemaName)).Error; err != nil { - t.Fatalf("drop schema %s: %v", schemaName, err) - } - }) return testDB🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/internal/services/testutil_pg_test.go` around lines 71 - 100, The cleanup is registered too late so failures after schema creation can leak the schema and DB connections; move the t.Cleanup registration to immediately after creating the schema (right after the adminDB.Exec CREATE SCHEMA success) and make the cleanup close both connection pools and drop the schema: call adminDB.DB().Close() and testDB.DB().Close() (or the gorm DB().Close equivalents) and execute DROP SCHEMA IF EXISTS "<schemaName>" CASCADE inside that cleanup so adminDB and testDB are always closed and the schema always removed even if migratePGTestDB or subsequent opens fail; update references in this function (adminDB, testDB, migratePGTestDB, withSearchPath) accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 221-224: The workflow uses older JavaScript action versions that
don't support Node 24; update the action references: change the actions/setup-go
usage (symbol "uses: actions/setup-go@v4") to use v6 and change the
actions/checkout usage (symbol "uses: actions/checkout@v4") to v5 or v6 so both
actions run on Node 24-compatible runners; after updating, verify the workflow
passes actionlint and that the runner version meets the actions' minimum (runner
v2.327.1+ for setup-go v6).
---
Outside diff comments:
In `@backend/internal/services/testutil_pg_test.go`:
- Around line 71-100: The cleanup is registered too late so failures after
schema creation can leak the schema and DB connections; move the t.Cleanup
registration to immediately after creating the schema (right after the
adminDB.Exec CREATE SCHEMA success) and make the cleanup close both connection
pools and drop the schema: call adminDB.DB().Close() and testDB.DB().Close() (or
the gorm DB().Close equivalents) and execute DROP SCHEMA IF EXISTS
"<schemaName>" CASCADE inside that cleanup so adminDB and testDB are always
closed and the schema always removed even if migratePGTestDB or subsequent opens
fail; update references in this function (adminDB, testDB, migratePGTestDB,
withSearchPath) accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f547e244-ba8f-406e-926c-5cff9d3d55d2
⛔ Files ignored due to path filters (1)
backend/go.sumis excluded by!**/*.sum
📒 Files selected for processing (4)
.github/workflows/ci.ymlbackend/go.modbackend/internal/services/testutil_pg_test.goscripts/check-backend-ci-cache.sh
💤 Files with no reviewable changes (1)
- scripts/check-backend-ci-cache.sh
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 requires Node 24-compatible actions. refs #293 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(deps): bump the deps group in /tachimint with 4 updates
Bumps the deps group in /tachimint with 4 updates: [axios](https://github.com/axios/axios), [i18next](https://github.com/i18next/i18next), [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).
Updates `axios` from 1.14.0 to 1.15.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.14.0...v1.15.0)
Updates `i18next` from 26.0.3 to 26.0.4
- [Release notes](https://github.com/i18next/i18next/releases)
- [Changelog](https://github.com/i18next/i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next/compare/v26.0.3...v26.0.4)
Updates `@types/node` from 25.5.2 to 25.6.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
Updates `typescript-eslint` from 8.58.0 to 8.58.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.1/packages/typescript-eslint)
---
updated-dependencies:
- dependency-name: axios
dependency-version: 1.15.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: deps
- dependency-name: i18next
dependency-version: 26.0.4
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: deps
- dependency-name: "@types/node"
dependency-version: 25.6.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: deps
- dependency-name: typescript-eslint
dependency-version: 8.58.1
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: deps
...
Signed-off-by: dependabot[bot] <support@github.com>
* feat(contracts): 實作 TachiToken Soulbound ERC-20
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test(contracts): 新增 TachiToken Foundry 單元測試
closes #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore(contracts): 補回 foundry.toml(誤刪修復)
contracts/foundry.toml 原由 #125(#128)建立,因 Codex 執行時
誤刪導致本 branch 工作目錄缺少此檔。內容與 420e012 完全相同,
不修改任何設定,僅確保 forge build / forge test 可正常執行。
refs #110
* docs: add tachimint Figma design prompts
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix(contracts): 補充 MAX_SUPPLY 單位註釋(wei)
review 回應:
- 項目 3:補 MAX_SUPPLY wei 單位說明
- 項目 2(burn 空實作):無需修改,_burn(from, amount) 於 L22 已存在,
reviewer 係從摘要判斷,非實際查閱原始碼
- 項目 4 邊界測試:test_mint_exceedsCap_reverts 已覆蓋
「mint 至 MAX_SUPPLY 後再 +1」的精確邊界,無需新增
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test(contracts): 補零地址、burn 零金額、approve 測試案例
review 回應(項目 1、2、4):
- 項目 1(零地址 mint):OZ v5 _mint() 已內建 ERC20InvalidReceiver revert,
合約層不加 require(避免冗餘),補測試記錄此行為
- 項目 2(burn 空實作):reviewer 誤判,_burn(from, amount) 於 L22 已存在,
無需修改
- 項目 4 測試缺口:
- 零地址測試 → 補上
- 邊界測試 → test_mint_exceedsCap_reverts 已覆蓋,無需新增
- burn 零金額 → 補上
- approve 行為 → 補上
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test(contracts): 鎖定 expectRevert 具體錯誤訊息
將 3 處 vm.expectRevert() 改為明確指定錯誤字串:
- test_mint_exceedsCap_reverts → bytes("TachiToken: cap exceeded")
- test_transfer_reverts → bytes("TachiToken: soulbound")
- test_transferFrom_reverts → bytes("TachiToken: soulbound")
L27(onlyOwner)與 L67(零地址)使用 OZ custom error,
不適用 bytes() 形式,維持 vm.expectRevert()。
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test(contracts): 補 burn 非 owner 負向測試
新增 test_burn_nonOwner_reverts,確保 burn() 權限回歸可被攔截。
vm.expectRevert() 維持裸形式(OZ OwnableUnauthorizedAccount
custom error,不適用 bytes() 鎖定),與 test_mint_nonOwner_reverts 一致。
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore: trigger CI re-run after scope police body fix
refs #110
* feat(contracts): override approve 封鎖 Soulbound allowance 路徑
approve 保留可用會製造「已授權但永遠無法轉移」的假象,前端走標準
ERC-20 approve flow 時會被誤導並浪費 gas。Phase 2 平台 Router
直接走 burn/mint,不需要 approval 路徑,一併封鎖語意才完整。
OZ v5 已移除 increaseAllowance / decreaseAllowance,
僅需 override approve 一個函數。
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test(contracts): 更新測試反映 approve 封鎖語意
- test_approve_succeeds_even_though_transfer_blocked
→ test_approve_reverts(approve 現在應 revert)
- test_transferFrom_reverts 移除 approve 前置步驟
(approve 已封鎖,無法作為 allowance 設定手段)
refs #110
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore: relax scope police for dependabot PRs
* [frontend] Extension Demo — 音效系統(Web Audio Bridge) (#171)
* feat: extension demo 音效系統
- 新增 useSound hook(Web Audio API 合成,無外部音效檔)
- 新增 content script audio bridge,讓 Discord/OBS 能捕捉 tab audio
- 挖礦點擊:5 層合成(impact transient、metallic overtone、bandpass noise、low thump、sparkle),3 variant(light 20%/normal 65%/critical 15%)隨機觸發
- 進度條完成:FF 勝利號角音符序列
- 點擊配額用完:雙聲綜藝答錯蜂鳴器
- SW 切換:短促 sine 音效
- 背景音樂:原創 G 大調 8-bit 冒險主題,獨立 ♪ ON/OFF 按鈕控制
- manifest.json 新增 content_scripts + tabs permission
- 安裝 @types/chrome、@types/react、@types/react-dom,新增 tsconfig.json
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: 移除 pnpm-lock.yaml,加入 .gitignore
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect 型別設定
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect bridge 行為
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect UI 細節
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect 測試敘述
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: clarify dependabot scope police behavior
refs #177
Co-Authored-By: Codex <codex[bot]@openai.com>
* feat(backend): 載入 contract env 並補 Sepolia 部署文件
- config.go 新增 ContractConfig,載入 TACHI_CONTRACT_ADDRESS / SEPOLIA_SIGNER_KEY
- backend/.env.example 補上兩個 env var 的佔位與安全說明
- deployments/sepolia.json 新增 ownerStrategy 記錄 MVP owner 策略
refs #175
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* docs(backend): 修正 .env.example 過時註解並補 SEPOLIA_SIGNER_KEY 說明
- 移除「尚未載入」的過時 Verification note,改為指向 config.go 載入路徑
- 補充 SEPOLIA_SIGNER_KEY 的用途、管理方式與安全警示
refs #175
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* [contract] Soulbound ERC-20 Sepolia 部署 + Etherscan 驗證 (#174)
* feat(contracts): 建立 Sepolia 部署 script 與環境設定
refs #111
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore(contracts): 記錄 Sepolia 部署資訊與合約地址
closes #111
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* revert: 移除 backend/.env.example 改動(跨 surface)
backend/.env.example 的 TACHI_CONTRACT_ADDRESS 調整應另開 backend ticket 處理。
refs #111
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* revert: 完全移除 backend/.env.example 改動
contracts surface 不可修改 backend/,TACHI_CONTRACT_ADDRESS 另開 ticket 處理。
refs #111
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* docs(contracts): README 補 source .env 載入步驟
refs #111
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore(deps-dev): bump vite in /tachimint in the vite group (#164)
Bumps the vite group in /tachimint with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).
Updates `vite` from 8.0.5 to 8.0.8
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.0.8/packages/vite)
---
updated-dependencies:
- dependency-name: vite
dependency-version: 8.0.8
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: vite
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(backend): use empty placeholder for SEPOLIA_SIGNER_KEY in .env.example
refs #175
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: 新增 TachiToken contract ABI binding
refs #112
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: 修正 nonce 競態、TOCTOU 及 ethclient 無條件啟動
- TachiToken: sync.Mutex 序列化 nonce 分配
- ClaimService: DB transaction 內先鎖行再 mint
- main.go: 合約設定為空時跳過 ethclient dial
refs #112
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* [frontend] Extension Demo — 音效系統 + Claim 提領介面 + HUD 金幣按鈕 + 洞穴背景 (#181)
* feat: extension demo 音效系統
- 新增 useSound hook(Web Audio API 合成,無外部音效檔)
- 新增 content script audio bridge,讓 Discord/OBS 能捕捉 tab audio
- 挖礦點擊:5 層合成(impact transient、metallic overtone、bandpass noise、low thump、sparkle),3 variant(light 20%/normal 65%/critical 15%)隨機觸發
- 進度條完成:FF 勝利號角音符序列
- 點擊配額用完:雙聲綜藝答錯蜂鳴器
- SW 切換:短促 sine 音效
- 背景音樂:原創 G 大調 8-bit 冒險主題,獨立 ♪ ON/OFF 按鈕控制
- manifest.json 新增 content_scripts + tabs permission
- 安裝 @types/chrome、@types/react、@types/react-dom,新增 tsconfig.json
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: 移除 pnpm-lock.yaml,加入 .gitignore
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect 型別設定
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect bridge 行為
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect UI 細節
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect 測試敘述
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 修正 extension sound effect 測試文案
refs #170
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: Claim 提領介面 + HUD 金幣按鈕 + 洞穴背景
- 新增 ClaimPanel(CPC→TCG 1:0.1 swap,MAX 按鈕、2s 自動 reset)
- DemoScreen 加入 'claim';App.tsx 新增 tcgBalance + handleClaim
- i18n claim.* keys(en / zh-TW / zh-CN)
- HUD CLAIM 按鈕改為 8 幀像素風旋轉金幣(正圓輪廓,crispEdges)
- useSound 新增 playClaimSound(3 層合成,~220ms)
- ClaimPanel handleClaim 觸發音效
- HUD 背景:SVG 岩壁 / 金礦石 / 水晶 + CSS 多層漸層洞穴氛圍
refs #180
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: restore sidepanel HUD bridge warning refs #180
* fix: address PR review issues refs #180
* chore: rerun PR checks refs #180
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: 限制 mint RPC context 並共用合約實例
refs #182
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: 修正 claim mint 一致性 review 意見
refs #182
Co-Authored-By: Codex <codex[bot]@openai.com>
* feat(backend): internal tachiya points query endpoint
- GET /api/v1/internal/tachiya/users/points/balance?email=xxx
- X-Tachiya-Internal-Secret header auth middleware
- config reads TACHIYA_INTERNAL_SHARED_SECRET
refs #183
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(backend): fix go.sum missing fsnotify entry for go-ethereum
refs #112
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: upgrade pgx dependency
refs #112
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: harden internal points endpoint
refs #183
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: add .go-build-cache/ to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: cover internal route auth registration
refs #183
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: add SpendService design spec for #186
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add SpendService implementation plan
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add TachiToken.Burn() method
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add SpendService.Redeem unit tests (failing)
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: implement SpendService.Redeem with reserve-then-burn flow
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: check RowsAffected in rollbackSpendReservation
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add SpendHandler POST /spend/redeem
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add binding tag to redeemRequest.Amount, document ErrSpendContractConfig fallthrough
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: wire SpendService and POST /api/v1/spend/redeem route
closes #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: preserve txHash when WaitMined fails to avoid DB/chain inconsistency
- TachiToken.Burn: return txHash on WaitMined failure so callers can
distinguish "tx broadcast but receipt unknown" from "tx never sent"
- SpendService.Redeem: only rollback DB when txHash is empty (tx not sent);
skip rollback when txHash is non-empty to prevent chain-burned / DB-restored inconsistency
- Add TestRedeem_BurnBroadcastedButReceiptUnknown to cover new behavior
- Update spec and plan docs (status, main.go path, flow description, MD040)
refs #186
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: apply SQLite pragmas via DSN in concurrent airdrop test
PRAGMA statements executed after Open only affect the single connection
that runs them. With SetMaxOpenConns(8), other pool connections lacked
busy_timeout/WAL mode and immediately failed with "database is locked".
Moving the settings to the DSN ensures every pool connection gets them.
refs #70
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: wire tachimint claim api
refs #190
Co-Authored-By: Codex <codex[bot]@openai.com>
* [frontend] Extension demo — coupon shop UI (#188)
* feat: add extension coupon shop UI
refs #15
Co-Authored-By: Codex <codex[bot]@openai.com>
* feat: polish extension coupon shop UI
refs #15
Co-Authored-By: Codex <codex[bot]@openai.com>
* feat: tune extension claim and coupon colors
refs #15
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: coupon shop atomic redeem, lifted state, i18n items
- Persist tcgBalance and redeemedCouponIds in demo state; sync refs for sync redeem path
- handleCouponRedeem returns success / insufficient / already_redeemed
- CouponShopPanel uses i18n for catalog copy and back label; redeem button guards with isRedeeming
- Extend App coupon tests for success and duplicate paths
refs #15
Made-with: Cursor
* chore: add PR #188 body file and gh helper for scope police
refs #15
Made-with: Cursor
* fix: move PR #188 GitHub body out of plans/
plans/ is for implementation plans; PR description text belongs under .github/.
refs #15
Made-with: Cursor
---------
Co-authored-by: Codex <codex[bot]@openai.com>
* fix: localize tachimint claim copy
refs #190
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: convert TACHI amounts to raw token units
refs #192
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: add demo wallet binding helper
refs #191
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: add AGENTS.md for Codex PR review optimization (#179)
* docs: update PR review strategy
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: harden GitHub Actions for production readiness
- Expand integration tests to run all packages (./...) instead of a single test case
- Add dashboard/ npm tracking to Dependabot
- Enable Dependabot security updates via gh api
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update AI collaboration guidelines to reduce Codex delegation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: add [infra] and [chore] PR title prefixes to scope police
- Allow [infra] and [chore] as valid PR title prefixes
- Exempt [infra] and [chore] PRs from backend contract checks
- Bootstrapping fix: [infra] PRs would be blocked by the old rules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: notify Discord only on CI failure
Replace always-on GitHub webhook with a GitHub Actions notify job
that fires only when CI fails. Disables the noisy GitHub webhook.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: upgrade axios to 1.15.0 in tachimint and dashboard
Fixes critical SSRF and header injection vulnerabilities (CVE).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: upgrade golang.org/x/oauth2 to v0.36.0
Fixes high severity input validation vulnerability in oauth2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add Sepolia claim/mint MVP plan and tachimint boundary docs (#226)
- docs/tachimint-loyalty-claim-boundary.md: T-Point vs $TACHI 產品邊界說明
- plans/sepolia-claim-mint-mvp.md: Sepolia MVP 完整計畫
- plans/sepolia-claim-mint-issue-breakdown.md: 建議出票順序
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: fix dependabot-automerge to avoid "No jobs were run" notifications
Restructure job to always run one step (skip message) for non-Dependabot
PRs, preventing GitHub from sending workflow notification emails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(deps-dev): bump the typescript-tooling group (#235)
Bumps the typescript-tooling group in /tachimint with 3 updates: [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js), [eslint](https://github.com/eslint/eslint) and [typescript](https://github.com/microsoft/TypeScript).
Updates `@eslint/js` from 9.39.4 to 10.0.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/commits/v10.0.1/packages/js)
Updates `eslint` from 9.39.4 to 10.2.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.4...v10.2.0)
Updates `typescript` from 5.8.3 to 6.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v6.0.2)
---
updated-dependencies:
- dependency-name: "@eslint/js"
dependency-version: 10.0.1
dependency-type: direct:development
update-type: version-update:semver-major
dependency-group: typescript-tooling
- dependency-name: eslint
dependency-version: 10.2.0
dependency-type: direct:development
update-type: version-update:semver-major
dependency-group: typescript-tooling
- dependency-name: typescript
dependency-version: 6.0.2
dependency-type: direct:development
update-type: version-update:semver-major
dependency-group: typescript-tooling
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump the react group in /tachimint with 2 updates (#236)
Bumps the react group in /tachimint with 2 updates: [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom).
Updates `react` from 19.2.4 to 19.2.5
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.5/packages/react)
Updates `react-dom` from 19.2.4 to 19.2.5
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.5/packages/react-dom)
---
updated-dependencies:
- dependency-name: react
dependency-version: 19.2.5
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: react
- dependency-name: react-dom
dependency-version: 19.2.5
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: react
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps-dev): bump the deps group in /tachimint with 2 updates (#237)
Bumps the deps group in /tachimint with 2 updates: [globals](https://github.com/sindresorhus/globals) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).
Updates `globals` from 17.4.0 to 17.5.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v17.4.0...v17.5.0)
Updates `typescript-eslint` from 8.58.1 to 8.58.2
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.2/packages/typescript-eslint)
---
updated-dependencies:
- dependency-name: globals
dependency-version: 17.5.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: deps
- dependency-name: typescript-eslint
dependency-version: 8.58.2
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: deps
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* [chore] 移除 demo wallet binding helper (#243)
* chore: 移除 demo wallet binding helper
Demo 階段已結束(refs #208),此 CLI 為 demo-only 工具,
不再需要維護。
refs #242
closes #198
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* docs: restore TACHI_CONTRACT_ADDRESS and SEPOLIA_SIGNER_KEY in README
refs #242
---------
Co-authored-by: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* [discussion] Define tachimint Chrome sidepanel migration decision (#247)
* docs: define tachimint Chrome sidepanel migration decision
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: keep discussion PR out of tachimint surface
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
* [discussion] narrow auth architecture baseline (#215)
* docs: narrow auth architecture baseline
refs #58
refs #34
* docs: link auth baseline doc in readme
refs #58
refs #34
* [frontend] split dashboard streamers pages from auth migration (#216)
* feat: split streamers pages from auth migration
refs #69
* test: tighten streamers fallback handling
refs #69
* chore: drop dashboard lockfile from streamers pr
refs #69
* chore: add dashboard lockfile for vitest and jsdom
refs #217
* fix: remove synchronous setState calls in effects to satisfy lint
refs #217
* fix: address streamers fallback review comments
refs #69
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Erick52106 <fs63505200210@gmail.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [backend] 錢包綁定前置 — auth_providers partial unique index + SIWE helpers 抽取 (#254)
* docs: wallet binding spec — POST /users/me/wallet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: fix wallet binding spec per review feedback
- SQLite 支援 partial index,test helper 應補同等 index
- step 6 補 RowsAffected == 1 防並發重放
- step 9 說明 step 8 soft delete 後 restore 邏輯
- lookupAddr 改用 strings.ToLower(checksumAddr)
- Create/restore 遇 unique violation 轉 ErrProviderLinked
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add implementation checklist and migration 014 to wallet binding spec
- 補 migration 014 為物件清單第 0 項
- 拆 siwe.go 為 1a(新增)/ 1b(修改 auth_service.go)
- 補 implementation checklist 避免隱含工作被漏
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: final spec polish before implementation plan
- checklist 路徑補 backend/ 前綴
- auth_service.go unused import 精準化(go-ethereum/crypto)
- swagger_types.go 補 WalletResponse 定義
- router 編號更新為 5
- test cases 補 nonce replay 與 race → ErrProviderLinked
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: nit fixes — checklist swagger_types, remove HTTP 200 from service test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: wallet binding implementation plan
5 tasks: migration, siwe extraction, UserService.LinkWallet (TDD),
UserHandler + swagger types, router. Full code in every step.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: migration 014 — partial unique index on auth_providers
Replaces UNIQUE(provider, provider_id) with a partial index scoped to
active rows (deleted_at IS NULL), enabling soft-delete + re-bind without
constraint violations. SQLite test helpers updated in both services and
handlers packages.
refs #249
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: extract SIWE helpers to services/siwe.go
siweMessage and verifyEthSignature shared between auth_service and
upcoming user_service.LinkWallet. Removes go-ethereum/crypto import
from auth_service.go.
refs #249
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: remove LinkWallet route from handler test env
Handler not yet implemented in this PR (comes in #253).
refs #251
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: siweMessage 加 issuedAt 參數,修正驗證非決定性問題
使用 nonceRecord.CreatedAt 重建訊息,確保簽章與驗證
使用完全相同的字串,消除 time.Now() 造成的競態。
refs #251
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: nonce API 回傳 issued_at,修正客戶端無法重建 SIWE 訊息問題
POST /auth/web3/nonce 現在回傳 {"nonce":"...","issued_at":"..."},
客戶端用 issued_at 建構與伺服器相同的 EIP-4361 訊息後簽署。
refs #251
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: Web3Nonce test 補錯誤斷言,避免靜默失敗
refs #251
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* [backend] Agency Onboarding — partial success recovery flow (#244)
* feat: add AgencyService.GetByID with onboarding status
onboarding_complete is derived from password_hash IS NOT NULL,
no schema change required.
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add GET /agencies/:id and POST /agencies/:id/resend-setup
GET returns profile + onboarding_complete (derived from password_hash).
POST resend-setup retriggers ForgotPassword; returns 500 on failure
so admin knows the resend did not succeed.
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: wire GET /agencies/:id and POST /agencies/:id/resend-setup; improve log format
Log messages now use key=value format (agency_id=, email=, err=)
for grep-friendly observability.
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add agency onboarding recovery implementation plan
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address code review — add onboarding_complete=true test and ForgotPassword comment
- Add TestAgencyHandler_Get_OnboardingComplete to cover handler-layer
onboarding_complete=true path (previously only tested at service layer)
- Add comment in ResendSetup explaining ForgotPassword silent-nil assumption
and when it would need to be revisited
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address CodeRabbit review comments
- ResendSetup: nil-guard user.Email before dereference, extract local email var
- Add TestAgencyHandler_ResendSetup_MailerError and DBError (500 failure paths)
- Fix outdated comment referencing old POST /auth/forgot-password endpoint
- plans: mark agency-onboarding-recovery as Status: Completed
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: add auth/role coverage for GET /agencies/:id and POST /agencies/:id/resend-setup
- TestAgencyHandler_Get_RequiresAuth (401)
- TestAgencyHandler_Get_ForbiddenRole (403 for non-admin/agency role)
- TestAgencyHandler_ResendSetup_RequiresAuth (401)
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: propagate non-NotFound DB errors from ForgotPassword
Previously ForgotPassword swallowed all errors from the email lookup,
meaning a transient DB failure would still return nil and cause
POST /agencies/:id/resend-setup to reply 200 even though no token was
written and no email was sent.
Now only gorm.ErrRecordNotFound is swallowed (anti-enumeration); other
errors are propagated to the caller.
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: block resend-setup for agencies that have completed onboarding
POST /agencies/:id/resend-setup now returns 409 Conflict if the agency
already has a password set, preventing an unsolicited password-reset
email from being sent to an already-onboarded agency.
refs #146
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* [backend] support refresh token cookies for auth refresh/logout (#220)
* feat: support auth refresh cookies
refs #217
* test: assert refresh cookie clearing
refs #217
* test: tighten auth cookie coverage and fix airdrop test seed
refs #217
Co-Authored-By: Codex <codex[bot]@openai.com>
* test: assert cleared refresh cookie remains httponly
refs #217
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: harden refresh cookie contract
* test: assert refresh cookie max age
---------
Co-authored-by: Erick52106 <fs63505200210@gmail.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [backend] 錢包綁定 service 層 — UserService.LinkWallet(SIWE 驗證 + soft delete 策略) (#256)
* feat: UserService.LinkWallet — SIWE-verified wallet binding
Allows an authenticated user to bind a MetaMask wallet. Implements:
- address validation and EIP-55 checksum normalization
- SIWE nonce + signature verification
- atomic nonce consumption with RowsAffected guard
- soft-delete of old provider + restore-or-insert pattern
- ErrProviderLinked on cross-user conflict or race
- TranslateError: true in DB config for consistent gorm.ErrDuplicatedKey
refs #249
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: TestLinkWallet 補齊 10 cases(含 nonce/signature/replay/restore)
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: LinkWallet nonce DB 錯誤分流、siweMessage 補 issuedAt 參數
- nonce 查詢非 RecordNotFound 錯誤直接往上拋,不再誤判為使用者輸入錯誤
- siweMessage 呼叫補第三個參數 issuedAt(nonceRecord.CreatedAt RFC3339)
修正與簽名端訊息不一致導致的驗證失敗
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: seedWalletNonce 回傳 record,補 siweMessage issuedAt 參數(測試)
- seedWalletNonce 改回傳 *models.Web3Nonce,讓測試取得 CreatedAt
- 9 個 siweMessage 呼叫補第三個參數 issuedAt(nr.CreatedAt RFC3339)
修正測試無法通過簽名驗證的問題
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test: 補 TestLinkWallet_RaceUniqueViolation(unique violation → ErrProviderLinked)
模擬並發寫入情境:goroutine 先替 userA 插入相同地址的 active AuthProvider,
再呼叫 LinkWallet(userB),驗證 gorm.ErrDuplicatedKey 正確轉譯為 ErrProviderLinked。
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: SIWE message 改用 checksummed address,符合 EIP-4361 規範
lookupAddr(小寫)只用於 nonce DB 查詢;
siweMessage 與 verifyEthSignature 改傳 checksumAddr,
確保與前端照 EIP-4361 簽名的格式一致。
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test: siweMessage 測試簽名改用 checksummed address
配合 production code 的 EIP-4361 修正,
測試中 siweMessage 第一個參數從 strings.ToLower(addr) 改為 addr。
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: Web3Nonce address 正規化改用 HexToAddress + ToLower
原本只做 strings.ToLower,無前綴地址會與 LinkWallet 的
HexToAddress().Hex()+ToLower 正規化結果不一致,
導致 nonce 查詢找不到 row。統一使用相同正規化邏輯。
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* fix: nonce Delete 移到 transaction 外,確保消耗獨立提交
原本 nonce Delete 在 transaction 內,後續回傳 ErrProviderLinked
等錯誤時整個 tx 回滾,nonce 未被消耗,可重複使用。
改為在 transaction 前單獨刪除並確認 RowsAffected == 1,
transaction 只負責 provider 狀態變更。
refs #252
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* chore: exempt Dependabot PRs from size/scope checks in Scope police
go.sum updates routinely exceed the 1800-line diff limit, causing
Dependabot PRs to always fail the required check. Policy checks were
already skipped for Dependabot; this extends the exemption to the
size and surface-separation checks as well.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: add extensions/tachigo-demo-sidepanel to Dependabot config
Ensures future Dependabot PRs for this directory target develop
instead of main.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add review workflow to CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* [frontend] feat(tachimint): add Chrome sidepanel runtime skeleton (#264)
* feat(tachimint): add Chrome sidepanel runtime skeleton
Establishes the Chrome Extension (Manifest v3) runtime foundation for
tachimint, enabling it to load as a Chrome sidepanel without touching
any existing product logic (hooks, App.tsx, api.ts, services).
- Add public/manifest.json (Manifest v3, sidePanel + storage permissions)
- Add sidepanel.html as Chrome sidepanel entry point
- Add src/extension/background.ts: minimal service worker that enables
openPanelOnActionClick behavior; audio synthesis deferred to PR 3
- Add src/extension/content.ts: empty placeholder content script
- Add src/extension/storage.ts: chrome.storage.local + localStorage fallback
- Add src/extension/types.ts: DemoState types ported from migration source
- Update vite.config.ts: multi-entry build; background.js and content.js
output without hash (Chrome service worker requires stable filenames)
- Update tsconfig.app.json: add "chrome" to types for @types/chrome
- Update package.json: add @types/chrome ^0.1.40 devDependency
Refs: #246
Part of: docs/tachimint-chrome-sidepanel-migration.md Step 1 of 4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address sidepanel storage review comments
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: address frontend review follow-up
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: fall back when chrome storage write fails
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix(tachimint): remove duplicate sidepanel action handling
* fix(tachimint): align sidepanel host permissions
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* test(tachimint): run extension tests in ci
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* chore: remove extensions/tachigo-demo-sidepanel from Dependabot config
Directory removed in PR #264.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: 更新 AI 分工——加入 Gemini CLI 為第三個協作工具
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* [infra] Skip backend integration for docs-only PRs (#274)
* ci: skip backend integration for docs-only PRs
refs #273
Co-Authored-By: Codex <codex[bot]@openai.com>
* ci: keep integration tests on scope bypass
refs #273
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
* [chore] Standardize agent review workflow (#272)
* docs: code review workflow refactored to use Gemini CLI
改用 Gemini CLI 執行代碼審查的步驟 4-5,替代多個 Haiku agents。
- 單一 Gemini agent 一次性審查和評分(5 個維度)
- 自動降級:Gemini 不可用時詢問改用 Haiku agents
- 符合 delegation 策略,減少 token 消耗
實作檔案:
- ~/.claude/scripts/code-review-with-gemini.sh (審查腳本)
- ~/.claude/scripts/code-review-gemini-score.sh (評分工具)
- code-review skill (步驟 4-5 改動)
詳見 docs/code-review-refactor.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: code review refactoring — production hardening & blocker fixes
修復初版實作的 3 個 blocker 與多個風險:
**Blockers:**
1. grep -oP → sed(macOS 兼容)
2. allowed-tools 補齊 git log / gh api / 脚本 / gemini / test / rm
3. Fallback 機制完整實現(marker file + skill step 4b)
**其他改進:**
- CLAUDE.md 動態獲取(gh api)
- git history 完整蒐集(git log)
- related PR comments 收集
- JSON 解析改用 sed
方案B 已生產可用。下次 code review 自動使用修復版本。
詳見 docs/code-review-refactor.md § Production Hardening
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: standardize agent review workflow
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: fix 3 high-priority issues from Codex review
**High Priority Fixes:**
1. gh pr diff failure handling
- Previously: silently converted to fake string, Gemini produced [] (false negative)
- Now: fails loudly with return 1, skips review entirely
- Prevents misleading audit results
2. Remove fake "related PR comments" claim
- Was: get_related_pr_comments() only listed filenames, not actual comments
- Now: deleted function, reduced dimensions from 5→4
- Removes false context that could mislead Gemini
3. Use gh pr review instead of gh pr comment
- Was: only gh pr comment (not a real GitHub review object)
- Now: gh pr review --request-changes / --approve
- Produces actual CHANGES_REQUESTED / APPROVED review state
Status: All 3 High issues fixed. Ready for Beta testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: add issue matching delegation rule
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: clarify review JSON contracts
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: address review workflow docs feedback
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: clarify gemini review dimensions
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: clarify review fallback boundary
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: document gemini cli delegation
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: clarify Gemini delegation workflow with task taxonomy
新增 Gemini 專責任務表格,明確列出 6 大類型工作:
- 代碼掃描、文件生成、測試草稿、Log 分析、依賴審查、PR 初審
確保團隊不浪費 Claude token 做可由 Gemini 勝任的重複性工作。
refs #GEMINI-WORKFLOW
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: address PR review feedback on delegation rules and documentation
- Update PR title from [discussion] to [docs]
- Add cross-reference from AGENTS.md to .claude/rules/delegation.md as canonical source
- Remove user-specific paths from code-review-refactor.md and add scope disclaimer
- Document .claude/rules/ directory convention in CLAUDE.md
- Mark dual JSON schema format as TODO for future unification
refs #272
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: clarify PR review instruction format and remove session metadata
- Add 下指令格式 section to CLAUDE.md: brief format for CodeRabbit/Codex comment URLs to avoid wasting tokens on lookups
- Remove session context metadata block from AGENTS.md (was appended by Codex session)
refs #272
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add PR review instruction format guidelines
- Add .claude/rules/pr-review-instructions.md: standard format for CodeRabbit/Codex comment URLs
- Explains why brief context avoids wasting tokens on lookups
refs #272
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* docs: add granularity principles for issue/commit/PR
- Add section on atomic commits, single-responsibility issues, and focused PRs
- Explains benefits: better review, traceability, rollback, and faster cycles
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* [infra] Fix backend-integration condition and remove ineffective Go cache (#277)
* docs: code review workflow refactored to use Gemini CLI
改用 Gemini CLI 執行代碼審查的步驟 4-5,替代多個 Haiku agents。
- 單一 Gemini agent 一次性審查和評分(5 個維度)
- 自動降級:Gemini 不可用時詢問改用 Haiku agents
- 符合 delegation 策略,減少 token 消耗
實作檔案:
- ~/.claude/scripts/code-review-with-gemini.sh (審查腳本)
- ~/.claude/scripts/code-review-gemini-score.sh (評分工具)
- code-review skill (步驟 4-5 改動)
詳見 docs/code-review-refactor.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: code review refactoring — production hardening & blocker fixes
修復初版實作的 3 個 blocker 與多個風險:
**Blockers:**
1. grep -oP → sed(macOS 兼容)
2. allowed-tools 補齊 git log / gh api / 脚本 / gemini / test / rm
3. Fallback 機制完整實現(marker file + skill step 4b)
**其他改進:**
- CLAUDE.md 動態獲取(gh api)
- git history 完整蒐集(git log)
- related PR comments 收集
- JSON 解析改用 sed
方案B 已生產可用。下次 code review 自動使用修復版本。
詳見 docs/code-review-refactor.md § Production Hardening
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* ci: optimize backend CI with caching and parallelization
實作四項優化:
1) Docker layer cache — 啟用 DOCKER_BUILDKIT
2) Go modules cache — actions/setup-go with cache: true
3) backend-integration 並行化 — needs 改為 [scope-gate]
4) integration tests 條件執行 — 只在 backend/ 檔案變更時跑
refs #276
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: fix backend-integration condition and remove ineffective Go cache
修復之前改動的三個問題:
1) 恢復 scope-gate 輸出 run_backend_integration(計算檔案路徑)
- 在所有早退路徑都明確設定此輸出
- push 事件、scope-exception、一般 PR 都輸出正確值
2) backend-integration 改用 scope-gate 的輸出而非無效 contains()
- 修復 GitHub Actions 表達式無法實際取得檔案列表的問題
- 恢復 backend/ contracts/ docker-compose* .github/workflows/ci.yml 路徑檢查
3) 移除 setup-go(Docker-only job 中無效)
- Go cache 在 container 內無效,Docker build 時 go mod 仍會重新下載
- 保留 DOCKER_BUILDKIT=1 以啟用 Docker layer cache
4) 恢復 backend-integration 依賴 backend job
- 確保單元測試先執行,整合測試才能跑
- 符合 branch protection required checks 預期
refs #276
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: add DOCKER_BUILDKIT to backend-integration build step
Fix CodeRabbit feedback:
1. Add DOCKER_BUILDKIT=1 env to backend-integration Build image step (parity with backend job)
2. Replace absolute paths with relative paths in code-review-refactor.md
refs #276
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add language tags to fenced code blocks (MD040)
- Line 52, 97, 226: Add `text` language tag to unlabeled code blocks
- Add blank lines before code blocks per MD031 requirements
refs #277
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add granularity principles for issue/commit/PR
- Add section on atomic commits, single-responsibility issues, and focused PRs
- Explains benefits: better review, traceability, rollback, and faster cycles
refs #272
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: remove AI division section (out of PR #277 scope)
This section declares Gemini CLI usage, which is out of scope for this PR
that focuses on CI optimization without introducing new tools.
Commit this tool-related decision to a separate PR or docs.
refs #277
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: remove granularity principles section (out of PR #277 scope)
This section is a documentation policy update unrelated to CI optimization.
Per CLAUDE.md scope rules, documentation changes should be in separate PRs.
Move this to docs/refine-granularity-guidelines PR instead.
refs #277
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [discussion] Standardize Gemini-assisted PR review flow (#278)
* docs: standardize gemini pr review flow
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: avoid heavy git fetches in PR review
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: prefer flash for gemini delegation
refs #271
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
Co-authored-by: Erick52106 <fs63505200210@gmail.com>
* [infra] add Git LFS tracking for tachimint assets (#280)
* chore: add Git LFS tracking for tachimint assets
refs #279
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: normalize tachimint asset pointer
refs #279
Co-Authored-By: Codex <codex[bot]@openai.com>
* docs: align LFS migrate asset patterns
refs #279
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
* docs: finalize PR review guidelines and agent responsibilities
- Add comprehensive PR review process with clear Gemini/Claude/Codex separation
- Document 3 review execution modes (standard/minimal/high-risk)
- Add structured output format (Summary/Blockers/Majors/Minors/Nits)
- Define interaction prompts for 4 decision scenarios
- Document Codex review guidelines to minimize token usage
- Update AGENTS.md with parallel operation rules and workflow details
refs #265
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: add close reason comment to auto-closed PRs
When scope-police auto-closes a PR, include a detailed comment listing
the scope violations before the close event. This way users see the
reason immediately without needing to find comments in the timeline.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: raise PR diff hard limit from 1800 to 2500 lines
Version upgrades with auto-generated diffs (Swagger, etc.) often exceed
1800 lines when combined with related changes. 2500 lines still maintains
reasonable reviewability while accommodating legitimate refactors.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: implement tiered diff limits with warning threshold
- hardMaxDiffLines: 1500 (blocks standard PRs, except release)
- warningDiffLines: 800 (warns, does not block)
- Release promotion PRs exempt from diff limits
- scope-exception label for legitimate exceptions:
migration, generated code, dependency bumps
Rationale: AI review token overhead increases sharply beyond 800 lines.
Hard limit at 1500 protects code quality while allowing necessary large PRs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: limit exception PRs to 2500 lines, release PRs unlimited
scope-exception label allows up to 2500 lines for legitimate exceptions
(migration, generated code, dependency bumps). Only release promotion
PRs (develop -> main) can exceed 2500 lines.
This prevents scope-exception from becoming a loophole for giant PRs.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add PR size guideline with performance bands
Include performance metrics from ChatGPT analysis:
- < 200 lines: optimal (instant review)
- 200-400 lines: good (standard review)
- 400-800 lines: acceptable but needs segmented review (token overhead)
- 800-1500 lines: risk zone (recommend split)
- 1500+ lines: hard block (exceptions only)
This guides authors toward performant PRs while enforcing hard limits.
Resolve merge conflict in AGENTS.md.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* [chore] Swagger 契約正規化與產生器版本對齊(移除 invalid "": []) (#275)
* chore: normalize swagger security output and align swag version
refs #270
Co-Authored-By: Codex <codex[bot]@openai.com>
* test: remove redundant t.Helper calls in swagger tests
refs #270
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: normalize swagger security contract for public endpoints
refs #270
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
* docs: clarify read-only operations don't require user confirmation
- `gh pr view`, `gh pr list`, `gh issue view`, `gh api` (read requests) can execute directly
- State-changing operations (comment, review, merge, etc) still require explicit user consent
refs #275
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* ci: exempt pure docs/template/metadata PRs from backend contract checks
為純文檔改動提供豁免機制:
- 若 PR 只改動 docs/、plans/、.github/ISSUE_TEMPLATE/、.github/PULL_REQUEST_TEMPLATE.md、
README.md、.gitignore、.gitattributes 等非產品文件,自動豁免 backend contract 聲明要求
- 改進正則表達式以支持更靈活的格式(前置 dash、多行匹配、全角冒號等)
- 在 scope police comment 中顯示 "Docs/template/metadata only" 模式指示
好處:
- 防止文檔改動被過度約束
- 保留 scope pollution 防護機制
- 改善團隊 DX(不需要每次加 label)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* [frontend] migrate demo app-shell foundations into tachimint (1/4) (#265)
* fix: address frontend review follow-up
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* feat(tachimint): add assets, styles, i18n and coupon catalog for app shell
- Add logo PNG and pixel fonts (PressStart2P, Zpix)
- Add src/styles/fonts.css and src/styles/index.css (pixel UI theme)
- Import new stylesheets in src/index.css
- Add src/extension/couponCatalog.ts with COUPON_METAS constant
- Extend i18n locales (en / zh-TW / zh-CN) with loading, login, hud,
nonViewer, coupon and error keys required by the new app shell;
preserve all existing claim.actions / claim.errors / contextLoading keys
- Simplify storage.ts: remove chrome→localStorage fallback path (chrome
storage.set no longer throws); remove corresponding test case
refs #246
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: stop reviving legacy sidepanel demo state
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: address coderabbit review comments
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: tighten i18n parity token checks
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: address tachimint app shell review regressions
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: tighten tachimint CI and font fallbacks
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: make workflow check CI-safe in frontend tests
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: address PR 265 review follow-ups
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* fix: mirror localStorage on Chrome write success to prevent state rollback
After a successful Chrome storage write, saveDemoState() now keeps
localStorage in sync as a fallback mirror instead of clearing it.
This ensures that if Chrome storage read later fails, loadDemoState()
can still recover the most recent state from localStorage.
Also updates docs/tachimint-chrome-sidepanel-migration.md with
implementation slice details (#265–#268) so the doc can serve as
the concrete source of truth for this PR.
refs #246
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: move app shell assets to git lfs
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Codex <codex[bot]@openai.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* [backend] 錢包綁定 API — POST /users/me/wallet(已登入 Twitch 使用者綁定 MetaMask) (#269)
* docs: swagger — POST /users/me/wallet(WalletResponse + LinkWalletInput)
refs #253
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* feat: UserHandler.LinkWallet — POST /users/me/wallet
Adds WalletResponse swagger type, LinkWallet handler(400/401/409/500
error mapping),testutil_test.go wallet route,以及 router 路由。
refs #253
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* test: handler tests for LinkWallet(6 cases)
補齊 6 handler test cases:NoAuth / InvalidAddress / InvalidNonce /
InvalidSignature / Success / WalletAlreadyLinked。
各 error case 驗證 HTTP status 及 error message。
handlerSIWEMessage 使用 checksummed address 與 nonce.CreatedAt 作為
issuedAt,與 service 邏輯對齊。
closes #253
Co-Authored-By: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
* docs: align LinkWallet 500 response in swagger
refs #253
Co-Authored-By: Codex <codex[bot]@openai.com>
* refactor: align LinkWallet response with WalletResponse swagger type
refs #253
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Claude Sonnet 4.6 <claude[bot]@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [chore] 新增任務拆細規則與 GitHub issue/PR template 更新 (#283)
* docs: clarify read-only operations don't require user confirmation
- `gh pr view`, `gh pr list`, `gh issue view`, `gh api` (read requests) can execute directly
- State-changing operations (comment, review, merge, etc) still require explicit user consent
refs #275
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* chore: add task/PR splitting rules to AGENTS.md, CLAUDE.md, and GitHub templates
- AGENTS.md: 新增 Task / PR 拆分規則(第 120-191 行)
- CLAUDE.md: 新增「何時應該拆細」checklist 和「Claude Code 實作前必檢」
- GitHub templates: 在 PR template、feature_request、bug_report 中新增 scope/non-goals/acceptance criteria/suggested PR split 字段
這次改動讓 Claude Code、Codex 和團隊成員在 issue、PR、實作前都會看到同一套協議。
refs #275
Co-Authored-By: Codex <codex[bot]@openai.com>
* chore: add .continue/ to .gitignore
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add Interface/Reference fields to feature and bug templates
補充「介面/規格」和「參考」欄位,避免需求落地時規格斷層。
Based on CodeRabbit feedback on PR #283:
- feature_request.md: 新增「介面/規格」(Go interface、API 規格、React props 等)
- feature_request.md: 新增「參考」(現有實作、範本路徑、設計文件)
- bug_report.md: 新增「相關代碼或介面」(受影響的函數、API、component)
- bug_report.md: 新增「參考」(相關 issue、commit、錯誤日誌位置)
這兩個欄位可防止實作時出現規格解讀差異,並加速定位現有參考實作。
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [frontend] add LoginScreen, LoadingScreen, LanguageSwitcher, useSound and theme to tachimint (2b/5) (#266)
* feat(tachimint): add LoginScreen, LoadingScreen, LanguageSwitcher, useSound and theme
- LoginScreen: pixel-art login form with username/password, i18n, error state
- LoadingScreen: animated progress bar with logo; fires onComplete callback
- LanguageSwitcher: compact flag-button toggle (EN / 繁 / 简)
- useSound: Web Audio API hook (coin collect, claim, redeem, BGM loop)
- theme/backgrounds.ts: shared gradient/panel background constants
refs #246
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: address coderabbit feedback
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Codex <codex[bot]@openai.com>
* [infra] Cache backend Docker build layers in CI (#281)
* ci: cache backend Docker builds
refs #276
Co-Authored-By: Codex <codex[bot]@openai.com>
* ci: execute backend CI cache wiring check in workflow
The check-backend-ci-cache.sh script verifies Docker Buildx configuration and
cache semantics but was not invoked by any automation. Add early-stage check
job to prevent regressions in cache setup.
Fixes: https://github.com/nurockplayer/tachigo/pull/281#discussion_r3105494502
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: update Gemini --yolo usage to default-off
Change Gemini usage recommendation from always using --yolo to conditional.
Default to regular execution with user confirmation prompts, use --yolo only
when explicitly confirmed safe to avoid accidental failures.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* [infra] CI — remove redundant cache-to from backend-integration job
backend-integration depends on backend which already writes to GHA cache.
Removing cache-to avoids redundant cache write overhead and saves CI time.
refs #285
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* Revert "docs: update Gemini --yolo usage to default-off"
This reverts commit 60b6f807bc461fe162d9b7eeb3a2f6228fed680f.
---------
Co-authored-by: Codex <codex[bot]@openai.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* feat: add tachimint core interactive components
refs #246
Co-Authored-By: Codex <codex[bot]@openai.com>
* [infra] CI — parallelize backend unit and integration tests (#288)
* [infra] CI — extract backend-build job and parallelize tests
Create independent backend-build job that builds image once, then backend
and backend-integration jobs download the artifact and run tests in parallel.
This reduces total CI time from (build + unit + integration) to
(build + max(unit, integration)).
Changes:
- New backend-build job: build → docker save → upload artifact
- backend job: download artifact → docker load → run unit tests
- backend-integration job: download artifact → docker load → run integration tests
- Both test jobs now depend on backend-build (parallel execution)
- notify-discord updated to include backend-build in needs
refs #285
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* fix: add pipefail protection to docker save export step
Ensure docker save command failure fails fast, preventing upload of
corrupted artifacts. Add explicit file size validation.
refs #285
* fix: add backend-ci gate job to enforce build failure checks
Ensure backend image build failures are reported as CI failures, not
skipped jobs, so PR merge is properly blocked by required checks.
The backend-ci gate depends on backend-build, backend, and
backend-integration. If backend-build fails, the gate fails, guaranteeing
required checks will block merge.
Update pr-scope-policy.md to reflect the new gate check name.
refs #285
* fix: backend-ci gate should allow scope-based skipped jobs
Only fail when backend-build, backend, or backend-integration actually
fail. Allow them to be skipped due to scope-gate rules.
refs #285
* fix: backend-ci gate should reject cancelled status
Use allowlist mode: only success or skipped are acceptable.
Prevents branch protection bypass when jobs are manually cancelled.
refs #285
* fix: use proper GitHub Actions env for job result checks
Cannot dynamically expand needs.$job.result via expressions.
Use env variables to pass values, then iterate in shell.
Fixes: https://github.com/nurockplayer/tachigo/pull/288#discussion_r3106991665
refs #285
* ci: trigger scope-gate re-evaluation with ASCII colon fix
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* [infra] Backend integration tests — testcontainers 取代 docker-compose postgres (#293)
* [infra] CI — extract backend-build job and parallelize tests
Create independent backend-build job that builds image once, then backend
and backend-integration jobs download the artifact and run tests in parallel.
This reduces total CI time from (build + unit + integration) to
(build + max(unit, integration)).
Changes:
- New backend-build job: build → docker save → upload artifact
- backend job: download artifact → docker load → run unit tests
- backend-integration job: download artifact → docker load → run integration tests
- Both test jobs now depend on backend-build (parallel execution)
- notify-discord updated to include backend-build in needs
refs #285
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* fix: add pipefail protection to docker save export step
Ensure docker save command failure fails fast, preventing upload of
corrupted artifacts. Add explicit file size validation.
refs #285
* fix: add backend-ci gate job to enforce build failure checks
Ensure backend image build failures are reported as CI failures, not
skipped jobs, so PR merge is properly blocked by required checks.
The backend-ci gate depends on backend-build, backend, and
backend-integration. If backend-build fails, the gate fails, guaranteeing
required checks will block merge.
Update pr-scope-policy.md to reflect the new gate check name.
refs #285
* fix: backend-ci gate should allow scope-based skipped jobs
Only fail when backend-build, backend, or backend-integration actually
fail. Allow them to be skipped due to scope-gate rules.
refs #285
* fix: backend-ci gate should reject cancelled status
Use allowlist mode: only success or skipped are acceptable.
Prevents branch protection bypass when jobs are manually cancelled.
refs #285
* fix: use proper GitHub Actions env for job result checks
Cannot dynamically expand needs.$job.result via expressions.
Use env variables to pass values, then iterate in shell.
Fixes: https://github.com/nurockplayer/tachigo/pull/288#discussion_r3106991665
refs #285
* ci: trigger…
Summary
用 testcontainers-go 取代 CI 中的
docker compose up -d --wait postgres,讓 integration tests 完全自包含。改動
backend/internal/services/testutil_pg_test.go:加入TestMain+ testcontainers,整個 test suite 共用一個 PostgreSQL 容器(UUID schema 隔離依然保留)backend/go.mod/go.sum:加入testcontainers-go v0.42.0.github/workflows/ci.yml:backend-integration job 改為直接在 runner 上go test -tags integration,移除 artifact download、docker load、docker compose up/down 步驟為什麼
目前 CI backend-integration job 需要先
docker compose up -d --wait postgres,再docker compose run app go test。testcontainers 讓測試程式碼自己管理 DB 容器,CI 更簡單,本地也不需要手動docker compose up就能跑 integration tests。Scope 對齊
Source of truth: #292 — Backend integration tests — 用 testcontainers 加速 DB 初始化
Depends on PR: #288
Backend contract already in develop:
本 PR 是否完全在 source of truth 範圍內?
本 PR 明確不做
refs #292
Summary by CodeRabbit
发布说明
重构
依赖更新